﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Media;
using System.IO;
using MontagsmalerApp.ViewModels;
using MontagsmalerApp.Utils;
using MontagsmalerApp.Models;

namespace MontagsmalerApp.Views
{
	/// <summary>
	/// Stellt den aktiven Malbereich der Anwendung
	/// </summary>
	public partial class DrawWindow : Window
  {
    #region Variables
    // Timer für den Refresh des Arc
    DispatcherTimer refreshTimer;

    // WebCam object
    WebCam webcam;
    #endregion

    #region Ctor
    /// <summary>
    /// Initializes a new instance of the <see cref="DrawWindow"/> class.
    /// </summary>
    /// <param name="spiel">The spiel.</param>
    public DrawWindow(Spiel spiel)
		{
			InitializeComponent();

      // Das übergebene Spiel im DataContext merken
      this.DataContext = spiel;

      // InkCanvas initialisieren, Daten meist nicht über Eigenschaften im Designer änderbar
      InkCanvas1.DefaultDrawingAttributes.Color = ConfigurationParameters.InkCanvas1DefaultDrawingAttributesColor();
      InkCanvas1.DefaultDrawingAttributes.Height = ConfigurationParameters.InkCanvas1DefaultDrawingAttributesHeight();
      InkCanvas1.DefaultDrawingAttributes.Width = ConfigurationParameters.InkCanvas1DefaultDrawingAttributesWidth();
      InkCanvas1.DefaultDrawingAttributes.StylusTip = System.Windows.Ink.StylusTip.Ellipse;

      // http-Server Info setzen
      LWebServerInfo.Content = Utils.Network.GetNetworkConnectionString();

      // Default Arc Duartion setzen
      //ArcTimerAnimation.Duration = new Duration(TimeSpan.FromSeconds(spiel.MaximaleSekundenBegriff));

      TBEnde.Visibility = System.Windows.Visibility.Hidden;

      // Refreshtimer starten
      StartRefreshTimer();

      spiel.NeueMalrundeEvent += new Spiel.NeueMalrundeHandler(spiel_NeueMalrundeEvent);

      spiel.NeuerBegriffEvent += new Spiel.NeuerBegriffHandler(spiel_NeuerBegriffEvent);
      spiel.BegriffBeendetEvent += new Spiel.BegriffBeendetHandler(spiel_BegriffBeendetEvent);

      spiel.MalrundeBeendetEvent += new Spiel.MalrundeBeendetHandler(spiel_MalrundeBeendetEvent);
   	}
    #endregion

    #region Spiel Events
    #region spiel_NeueMalrundeEvent
    /// <summary>
    /// Spiel_s the neue malrunde event.
    /// </summary>
    void spiel_NeueMalrundeEvent()
    {
      ClearDrawingArea();
      InkCanvas1.IsEnabled = true;

      // Probemodus Hinweis
      TBEnde.Text = "Probemodus für " + ((Spiel)DataContext).AktuellerSpieler.Name;
      TBEnde.Visibility = System.Windows.Visibility.Visible;
    }
    #endregion

    #region spiel_NeuerBegriffEvent
    /// <summary>
    /// Spiel_s the neuer begriff event.
    /// </summary>
    void spiel_NeuerBegriffEvent()
    {
      ClearDrawingArea();
      InkCanvas1.IsEnabled = true;
      
      TBEnde.Visibility = System.Windows.Visibility.Hidden;

      // Start Animation
      //myStoryboard.Begin();
    }
    #endregion

    #region spiel_BegriffBeendetEvent
    /// <summary>
    /// Spiel_s the begriff beendet event.
    /// </summary>
    /// <param name="erraten">if set to <c>true</c> [erraten].</param>
    void spiel_BegriffBeendetEvent(Begriff aktuellerBegriff, bool erraten)
    {
      InkCanvas1.IsEnabled = false;

      string filename = DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + ((Spiel)DataContext).AktuellerSpieler.Name + "_" + aktuellerBegriff + "_" +(erraten?"OK":"Falsch");

      // Bild speichern
      ExportToJpeg(filename + ".png", InkCanvas1);
    }
    #endregion

    #region spiel_MalrundeBeendetEvent
    /// <summary>
    /// Spiel_s the malrunde beendet event.
    /// </summary>
    void spiel_MalrundeBeendetEvent()
    {
      // Probemodus Hinweis
      TBEnde.Text = "Malrunde beendet!";
      TBEnde.Visibility = System.Windows.Visibility.Visible;
    }
    #endregion
    #endregion

    #region Window_Loaded
    /// <summary>
    /// Handles the Loaded event of the Window control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
      if (ConfigurationParameters.GetWebCamNutzen())
      {
        try
        {
          webcam = new WebCam();
          webcam.InitializeWebCam(ref imgVideo);
          webcam.Start();
        }
        catch (Exception ex)
        {
          // Exception abfangen, handling aber nicht erforderlich - Dann gibt es eben kein WebCam-Video
          // Fehlermeldung der WebCam Lib kommt ebenfalls und muss vom Anwender weggeklickt werden!
        }

        imgVideo.Visibility = System.Windows.Visibility.Visible;
      }
      else
      {
        imgVideo.Visibility = System.Windows.Visibility.Hidden;
      }
    }
    #endregion
    
    #region Window_Closed
    /// <summary>
    /// Handles the Closed event of the Window control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void Window_Closed(object sender, EventArgs e)
    {
      // Stop the refresh timer
      StopRefreshTimer();

      // Check for webcam and stop
      if (webcam != null)
      {
        webcam.Stop();
      }
    }
    #endregion

    #region RefreshTimer
    #region StartRefreshTimer
    /// <summary>
    /// Starts the refresh timer.
    /// </summary>
    private void StartRefreshTimer()
    {
      if (refreshTimer == null)
      {
        // Initialize refresh timer
        refreshTimer = new DispatcherTimer();
        refreshTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
        refreshTimer.Tick += new EventHandler(refreshTimer_Tick);
      }

      // Start timer
      refreshTimer.Start();
    }
    #endregion

    #region refreshTimer_Tick
    /// <summary>
    /// Handles the Tick event of the refreshTimer control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void refreshTimer_Tick(object sender, EventArgs e)
    {
      //ArcTimer.InvalidateVisual();
    }
    #endregion

    #region StopRefreshTimer
    /// <summary>
    /// Stops the refresh timer.
    /// </summary>
    private void StopRefreshTimer()
    {
			if (refreshTimer != null)
			{
				refreshTimer.Stop();
				refreshTimer = null;
			}
    }

    #endregion
    #endregion

    #region ExportToJpeg
    /// <summary>
    /// Export InkCanvas to file
    /// </summary>
    /// <param name="path"></param>
    /// <param name="surface"></param>
    private void ExportToJpeg(String path, InkCanvas surface)
    {
      double
              x1 = surface.Margin.Left,
              x2 = surface.Margin.Top,
              x3 = surface.Margin.Right,
              x4 = surface.Margin.Bottom;

      if (path == null) return;

      surface.Margin = new Thickness(0, 0, 0, 0);

      Size size = new Size(surface.ActualWidth, surface.ActualHeight);
      surface.Measure(size);
      surface.Arrange(new Rect(size));

      RenderTargetBitmap renderBitmap =
       new RenderTargetBitmap(
         (int)size.Width,
         (int)size.Height,
         96,
         96,
         PixelFormats.Default);
      renderBitmap.Render(surface);
      using (FileStream fs = File.Open(path, FileMode.Create))
      {
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
        encoder.Save(fs);
      }
      surface.Margin = new Thickness(x1, x2, x3, x4);
    }
    #endregion

    #region ClearDrawingArea
    /// <summary>
    /// Löscht den Zeichenbereich
    /// </summary>
    private void ClearDrawingArea()
    {
      InkCanvas1.EditingMode = InkCanvasEditingMode.None;
      InkCanvas1.Strokes.Clear();
      InkCanvas1.EditingMode = InkCanvasEditingMode.Ink;
    }
    #endregion

    #region Window_KeyUp
    /// <summary>
    /// Handles the KeyUp event of the Window control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param>
    private void Window_KeyUp(object sender, KeyEventArgs e)
    {
      switch (e.Key)
      {
        // Clear drawing area
        case Key.End:
          ClearDrawingArea();
          break;
        // Show cam window
        case Key.C:
          imgVideo.Visibility = (imgVideo.Visibility == System.Windows.Visibility.Visible? System.Windows.Visibility.Hidden:System.Windows.Visibility.Visible);
          ConfigurationParameters.SetValue("WebCamNutzen", (imgVideo.Visibility == System.Windows.Visibility.Visible?true.ToString():false.ToString()));
          break;
        case Key.F:
          ChangePenColor();
          break;
        case Key.B:
          InkCanvas1.DefaultDrawingAttributes.Height++;
          InkCanvas1.DefaultDrawingAttributes.Width++;

          ConfigurationParameters.SetValue("InkCanvas1.DefaultDrawingAttributes.Height", InkCanvas1.DefaultDrawingAttributes.Height.ToString());
          ConfigurationParameters.SetValue("InkCanvas1.DefaultDrawingAttributes.Width", InkCanvas1.DefaultDrawingAttributes.Width.ToString());
          break;
        case Key.V:
          InkCanvas1.DefaultDrawingAttributes.Height--;
          InkCanvas1.DefaultDrawingAttributes.Width--;

          ConfigurationParameters.SetValue("InkCanvas1.DefaultDrawingAttributes.Height", InkCanvas1.DefaultDrawingAttributes.Height.ToString());
          ConfigurationParameters.SetValue("InkCanvas1.DefaultDrawingAttributes.Width", InkCanvas1.DefaultDrawingAttributes.Width.ToString());
          break;
      }
    }
    #endregion

    private void ChangePenColor()
    {
      if (InkCanvas1.DefaultDrawingAttributes.Color == Colors.Red)
      {
        InkCanvas1.DefaultDrawingAttributes.Color = Colors.Green;
      }
      else if (InkCanvas1.DefaultDrawingAttributes.Color == Colors.Green)
      {
        InkCanvas1.DefaultDrawingAttributes.Color = Colors.White;
      }
      else if (InkCanvas1.DefaultDrawingAttributes.Color == Colors.White)
      {
        InkCanvas1.DefaultDrawingAttributes.Color = Colors.Black;
      }
      else if (InkCanvas1.DefaultDrawingAttributes.Color == Colors.Black)
      {
        InkCanvas1.DefaultDrawingAttributes.Color = Colors.Red;
      }

      ConfigurationParameters.SetValue("InkCanvas1.DefaultDrawingAttributes.Color", InkCanvas1.DefaultDrawingAttributes.Color.ToString());
    }
  }
}
